package view;

import java.awt.EventQueue;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.KeyStroke;
import javax.swing.Timer;

import net.miginfocom.swing.MigLayout;
import javax.swing.JButton;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.Toolkit;

import javax.swing.BorderFactory;
import javax.swing.JSlider;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
import java.awt.event.ActionListener;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.Hashtable;

import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.beans.PropertyChangeListener;
import java.awt.event.ActionEvent;
import javax.swing.SwingConstants;

@SuppressWarnings("serial")
public class Workspace extends JFrame 
{
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				try {
					Workspace frame = new Workspace();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	private EventListener controller;
	private JPanel contentPane;
	private JPanel cueArea;
	private JPanel currentlyHighlighted;
	private Color currentlyHighlightedColor;
	private JLabel loadTimeLabel;
	private JTextArea notesTextField;
	private JLabel deckLabel;
	private ArrayList<CuePanel> cueHolder;
	private JPanel goPanel;
	private JPanel inspector;
	private Timer timer;
	private boolean inspectorDown;
	private JLabel numCuesLabel;
	private boolean somethingSelected;

	public Workspace()
	{
		new Workspace(null);
	}

	/**
	 * Create the frame.
	 */
	public Workspace(EventListener controller) 
	{
		this.controller = controller;
		cueHolder = new ArrayList<CuePanel>();
		inspectorDown = true;

		System.setProperty("apple.laf.useScreenMenuBar", "true");
		System.setProperty("awt.useSystemAAFontSettings","on");
		System.setProperty("swing.aatext", "true");
		System.setProperty("apple.awt.textantialiasing", "on");
		System.setProperty("apple.awt.antialiasing", "on");
		System.setProperty("apple.awt.rendering", "quality");
		
		setTitle("JMIDI by Brian Bagdasarian & Ben Vigman");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 1000, 700);
		setMinimumSize(new Dimension(700, 625));
		addMouseListener((MouseListener) controller);
		addKeyListener((KeyListener) controller);

		contentPane = new JPanel();
		contentPane.setLayout(new MigLayout("insets 5, gap 5", "[grow,left][grow][grow][grow][grow][grow][grow][grow]", "[55px:55px:55px,grow][90px:90px:90px,grow][grow][grow][grow][grow][grow][15px:15px:15px,grow]"));
		setContentPane(contentPane);

		JMenuBar menuBar = createMenuBar();
		setJMenuBar(menuBar);

		JPanel optionsBar = createOptionsBar();
		contentPane.add(optionsBar, "cell 0 0 8 1,growx,aligny center");

		goPanel = createGoPanel(controller);
		JPanel horizontalPanel = createHorizontalPanel();

		JSplitPane horizontalSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, goPanel, horizontalPanel);
		horizontalSplit.setBorder(BorderFactory.createEmptyBorder());
		horizontalSplit.setResizeWeight(0);
		horizontalSplit.setOneTouchExpandable(true);
		horizontalSplit.setContinuousLayout(true);
		horizontalSplit.setMinimumSize(new Dimension());
		horizontalSplit.addPropertyChangeListener((PropertyChangeListener) controller);

		JPanel sidePanel = createSidePanel(controller);

		cueArea = new TexturedPanel();
		cueArea.setBackground(Color.WHITE);
		cueArea.setLayout(new MigLayout("insets 0, gap 0", "[grow]", "[][]"));
		cueArea.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
		cueArea.addMouseListener((MouseListener) controller);

		JPanel cueTitleBar = createCueTitleBar();
		cueArea.add(cueTitleBar, "flowy,cell 0 0,growx,aligny center,wrap");

		JPanel lowerPanel = new JPanel();
		lowerPanel.setLayout(new MigLayout("insets 0", "[grow][grow 5000]", "[grow]"));
		lowerPanel.add(sidePanel, "cell 0 0,grow");
		lowerPanel.add(cueArea, "cell 1 0,grow");

		JSplitPane verticalSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, horizontalSplit, lowerPanel);
		verticalSplit.setBorder(BorderFactory.createEmptyBorder());
		verticalSplit.setResizeWeight(0);
		verticalSplit.setOneTouchExpandable(true);
		verticalSplit.setContinuousLayout(true);
		verticalSplit.addPropertyChangeListener((PropertyChangeListener) controller);

		contentPane.add(verticalSplit, "cell 0 1 8 6,grow");
		horizontalSplit.setDividerLocation(120);
		verticalSplit.setDividerLocation(95);

		inspector = new JPanel();
		contentPane.add(inspector, "cell 0 7 8 1,grow");
		inspector.setLayout(new MigLayout("insets -2 3 0 2, gap 0", "[]", "[grow]"));

		numCuesLabel = new JLabel("0 cues");
		inspector.add(numCuesLabel, "cell 0 0");
		
	}

	private JPanel createSidePanel(EventListener controller)
	{
		JPanel sidePanel = new JPanel();
		sidePanel.setLayout(new GridLayout(2, 0, 0, 0));

		JButton cueCreatorButton = new JButton("Cue Creator");
		cueCreatorButton.setFocusable(false);
		cueCreatorButton.addActionListener((ActionListener) controller);
		cueCreatorButton.setActionCommand("Create Cue");
		sidePanel.add(cueCreatorButton);

		JButton btnNewButton_1 = new JButton(":-(");
		btnNewButton_1.setFocusable(false);
		btnNewButton_1.addActionListener((ActionListener) controller);
		btnNewButton_1.setActionCommand("bleh");
		sidePanel.add(btnNewButton_1);

		return sidePanel;
	}

	private JPanel createCueTitleBar()
	{
		JPanel cueTitleBar = new JPanel();
		cueTitleBar.setLayout(new MigLayout("insets 0, gap 0", "[50px:50px:50px,grow 25][50px:50px:50px,grow 15][grow 150][175px:175px:175px,grow 50][121.5px:121.5px:121.5px,grow 40][121.5px:121.5px:121.5px,grow 40]", "[26px:26px:26px]"));

		JLabel lblNewLabel = new JLabel("Type");
		lblNewLabel.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel, "cell 0 0,width 10,alignx center,gapx 0,aligny center");

		JLabel lblNewLabel_1 = new JLabel("#");
		lblNewLabel_1.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel_1, "cell 1 0,width 10,alignx center,gapx 0,aligny center");

		JLabel lblNewLabel_2 = new JLabel("Q");
		lblNewLabel_2.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel_2, "cell 2 0,width 10,alignx center,gapx 0,aligny center");

		JLabel lblNewLabel_3 = new JLabel("Target");
		lblNewLabel_3.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel_3, "cell 3 0,width 10,alignx center,gapx 0,aligny center");

		JLabel lblNewLabel_4 = new JLabel("Pre Wait");
		lblNewLabel_4.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel_4, "cell 4 0,width 10,alignx center,gapx 0,aligny center");

		JLabel lblNewLabel_5 = new JLabel("Action Length");
		lblNewLabel_5.setFont(new Font("Lucida Grande", Font.PLAIN, 14));
		cueTitleBar.add(lblNewLabel_5, "cell 5 0,width 10,alignx center,gapx 0,aligny center");

		return cueTitleBar;
	}

	private JPanel createHorizontalPanel()
	{
		JPanel horizontalPanel = new JPanel();
		horizontalPanel.setBackground(new Color(238, 238, 238));
		horizontalPanel.setOpaque(false);
		horizontalPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
		horizontalPanel.setLayout(new MigLayout("insets 1, gap 3", "[grow]", "[43px:43px:43px][43px,grow]"));
		horizontalPanel.setMinimumSize(new Dimension(250, 0));

		JPanel deckPanel = new JPanel();
		deckPanel.setLayout(new MigLayout("insets 0, novisualpadding, gap 0", "[grow]", "[grow]"));
		deckPanel.setBackground(Color.BLACK);
		deckPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
		deckLabel = new JLabel();
		deckLabel.setOpaque(true);
		deckLabel.setForeground(Color.GREEN);
		deckLabel.setText(" [no cue on deck]");
		deckLabel.setFont(new Font("Helvetica", Font.BOLD, 24));
		deckLabel.setBackground(Color.BLACK);
		deckPanel.add(deckLabel, "cell 0 0,grow");
		horizontalPanel.add(deckPanel, "cell 0 0,grow");

		JPanel notesPanel = new JPanel();
		notesPanel.setLayout(new GridLayout(0, 1, 0, 0));
		notesPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
		notesTextField = new JTextArea();
		notesTextField.setFont(new Font("Helvetica", Font.PLAIN, 16));
		notesTextField.setFocusable(false);
		notesTextField.setLineWrap(true);
		notesTextField.setBackground(Color.WHITE);
		notesTextField.setColumns(10);
		notesTextField.addFocusListener((FocusListener) controller);
		JScrollPane notesScrollPane = new JScrollPane(notesTextField);
		notesScrollPane.setBorder(BorderFactory.createEmptyBorder());
		notesPanel.add(notesScrollPane);
		horizontalPanel.add(notesPanel, "cell 0 1,grow");

		return horizontalPanel;
	}

	private JPanel createGoPanel(EventListener controller)
	{
		JPanel goPanel = new JPanel();
		goPanel.setMinimumSize(new Dimension());
		JButton goButton = new JButton("GO");
		goButton.setFocusable(false);
		goButton.setActionCommand("GO");
		goButton.addActionListener((ActionListener) controller);
		goPanel.setLayout(new MigLayout("insets 0", "[120px,grow]", "[95px,grow]"));
		goButton.setFont(new Font("Helvetica", Font.BOLD, 32));
		goPanel.add(goButton, "cell 0 0,grow");

		return goPanel;
	}

	private JPanel createOptionsBar()
	{
		JPanel optionsBar = new JPanel();
		optionsBar.setLayout(new MigLayout("insets 0", "[][][][][][][grow][][][]", "[grow]"));

		JPanel stopAllPanel = createOptionPanel("Stop All", "Icon Graphics/Stop Sign.png");
		optionsBar.add(stopAllPanel, "cell 4 0,growx,aligny center");

		JPanel resetAllPanel = createOptionPanel("Reset All", "Icon Graphics/Reset.png");
		optionsBar.add(resetAllPanel, "cell 3 0,growx,aligny center");

		JPanel activeCuesPanel = createOptionPanel("Active Cues", "Icon Graphics/Active Cues.png");
		optionsBar.add(activeCuesPanel, "cell 2 0,growx,aligny center");

		JPanel toolboxPanel = createOptionPanel("Toolbox", "Icon Graphics/Toolbox.png");
		optionsBar.add(toolboxPanel, "cell 1 0,growx,aligny center");

		JPanel inspectorPanel = createOptionPanel("Inspector", "Icon Graphics/Inspector.png");
		optionsBar.add(inspectorPanel, "cell 0 0,growx,aligny center");

		JPanel loadPanel = createOptionPanel("Load", "Icon Graphics/Load.png");
		optionsBar.add(loadPanel, "cell 5 0,growx,aligny center");

		JPanel loadSliderPanel = new JPanel();
		loadSliderPanel.setLayout(new MigLayout("insets 0, gapx -30", "[grow][]", "[]"));

		JSlider loadSlider = new JSlider();
		loadSlider.setEnabled(false);
		loadSlider.setFocusable(false);
		loadSlider.setValue(0);
		Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
		labelTable.put(new Integer(50), new JLabel("Load to Time") );
		loadSlider.setLabelTable(labelTable);
		loadSlider.setPaintLabels(true);
		loadSliderPanel.add(loadSlider, "flowx,pad 0 0 0 0,cell 0 0,growx,gapx -10,aligny center");

		loadTimeLabel = new JLabel("0:00");
		loadSliderPanel.add(loadTimeLabel, "pad 0 0 15 0,cell 1 0,gapx -5,aligny top");
		optionsBar.add(loadSliderPanel, "cell 6 0,growx,aligny center");

		JPanel lockPanel = createOptionPanel("Unlocked", "Icon Graphics/Unlock.png");
		optionsBar.add(lockPanel, "cell 7 0,growx,aligny center");

		JPanel preferencesPanel = createOptionPanel("Preferences", "Icon Graphics/Preferences.png");
		optionsBar.add(preferencesPanel, "cell 8 0,growx,aligny center");

		JPanel drawerPanel = createOptionPanel("Cue Lists", "Icon Graphics/Drawer.png");
		optionsBar.add(drawerPanel, "cell 9 0,growx,aligny center");

		return optionsBar;
	}

	private JMenuBar createMenuBar()
	{
		JMenuBar menuBar = new JMenuBar();

		JMenu mnFile = new JMenu("File");
		menuBar.add(mnFile);
		
		JMenuItem simpleMode = new JMenuItem("Simple Mode");
		simpleMode.setActionCommand("Switch to Simple");
		simpleMode.addActionListener((ActionListener) controller);
		simpleMode.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
		mnFile.add(simpleMode);

		JMenu mnEdit = new JMenu("Edit");
		menuBar.add(mnEdit);
		
		JMenuItem delete = new JMenuItem("Delete");
		delete.setActionCommand("Delete");
		delete.addActionListener((ActionListener) controller);
		delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
		mnEdit.add(delete);
		
		JMenuItem moveUp = new JMenuItem("Move Up");
		moveUp.setActionCommand("Move Up");
		moveUp.addActionListener((ActionListener) controller);
		delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));

		JMenu mnCues = new JMenu("Cues");
		menuBar.add(mnCues);

		JMenu mnAbout = new JMenu("About");
		menuBar.add(mnAbout);

		return menuBar;
	}

	private JPanel createOptionPanel(String text, String filepath)
	{
		OptionPanel newOption = new OptionPanel(text, filepath, controller);
		return newOption;
	}

	public void addCue(String[] cueInfo)
	{
		/**
		 * Length of 7
		 * AUDIO CUES -> DISREGARD newCueInfo[3-5]
		 * newCueInfo[0] = CUE TYPE		
		 * newCueInfo[1] = LABEL
		 * newCueInfo[2] = JMIDI CUE NUMBER
		 * newCueInfo[3] = MSC TYPE
		 * newCueInfo[4] = MSC CUE NUMBER
		 * newCueInfo[5] = MSC COMMAND
		 * newCueInfo[6] = FILE PATH (for audio cues only)
		 */

		CuePanel newCue = new CuePanel(cueInfo, (MouseListener) controller);
		cueArea.add(newCue, "growx,aligny baseline, flowy, wrap 0");

		cueHolder.add(newCue);

		this.invalidate();
		this.validate();
		this.repaint();
	}

	public void setDisplayedLoadTime(String time) 
	{
		loadTimeLabel.setText(time);
	}

	public void reorder(int from, int to)
	{
		CuePanel mover = cueHolder.remove(from);
		if(to < cueHolder.size())
			cueHolder.add(to, mover);
		else
			cueHolder.add(mover);

		cueArea.remove(from+1);

		cueArea.add(mover, "growx,aligny baseline, flowy, wrap 0", to+1);

		this.invalidate();
		this.validate();
		this.repaint();
	}

	public void insert(int to, CuePanel inserted)
	{
		if(to < cueHolder.size())
			cueHolder.add(to, inserted);
		else
			cueHolder.add(inserted);

		cueArea.add(inserted, "growx,aligny baseline, flowy, wrap 0", to+1);

		this.invalidate();
		this.validate();
		this.repaint();
	}

	public void hideItem(JComponent item)
	{
		item.setVisible(false);
	}

	public void displayItem(JComponent item, JSplitPane divider)
	{
		item.setVisible(true);
		divider.setDividerLocation(93);
	}

	public void initiateInspectorSlide()
	{
		timer = new Timer(20, (ActionListener) controller);

		if(inspectorDown)
			timer.setActionCommand("timerUp");
		else
			timer.setActionCommand("timerDown");
		timer.start();	

	}
	public void slideInspector(boolean down)
	{		
		int currentSize = inspector.getHeight();
		String newSize = "";

		if(down)
		{	
			inspectorDown = true;
			newSize = Integer.toString(currentSize-5);
			if(currentSize<=20)
			{
				numCuesLabel.setVisible(true);
				timer.stop();
			}	
		}
		else
		{
			numCuesLabel.setVisible(false);
			inspectorDown = false;
			newSize = Integer.toString(currentSize+5);
			if(currentSize>=175)
				timer.stop();
		}

		MigLayout layout = (MigLayout) contentPane.getLayout();
		String rc = (String) layout.getRowConstraints();
		String firstPartRC = rc.substring(0, rc.indexOf("[grow]")+6);

		layout.setRowConstraints(firstPartRC + "[" + newSize + "px:" + newSize + "px:" + newSize + "px,grow]");
		inspector.setSize(inspector.getWidth(), Integer.parseInt(newSize));

		invalidate();
		validate();
		repaint();
	}

	public void select(CuePanel source, String notes)
	{
		this.highlight(((JPanel) source));
		this.showLoadedCue(((CuePanel) source).getLabel(), ((CuePanel) source).getCueNumber());
		this.showNotes(notes);
		somethingSelected = true;
	}
	
	public void unselect()
	{
		this.unHighlight();
		this.clearDeck();
		this.clearNotes();
		somethingSelected = false;
	}

	private void highlight(JPanel selected) 
	{
		unHighlight();
		currentlyHighlighted = selected;
		currentlyHighlightedColor = selected.getBackground();
		selected.setBackground(new Color(135, 206, 250));
		selected.setOpaque(true);
	}

	private void unHighlight()
	{
		try
		{
			currentlyHighlighted.setOpaque(false);
			currentlyHighlighted.setBackground(currentlyHighlightedColor);
		}
		catch(NullPointerException e) {}
	}

	private void showLoadedCue(String label, String cueNum) 
	{
		deckLabel.setText(" " + cueNum + " : " + label);
	}
	
	private void clearDeck()
	{
		deckLabel.setText(" [no cue on deck]");	
	}
	
	private void showNotes(String notes)
	{
		notesTextField.setText(notes);
		notesTextField.setFocusable(true);
	}
	
	private void clearNotes()
	{
		notesTextField.setFocusable(false);
		notesTextField.setText("");
	}
	
	public String getNotes()
	{
		return notesTextField.getText();
	}
	
	public int getSelectedCueNumber()
	{
		return Integer.parseInt(((CuePanel)currentlyHighlighted).getCueNumber());
	}

	public boolean isSomethingSelected()
	{
		return somethingSelected;
	}
	
	public void setNumCuesLabel(int number)
	{
		if(number==1)
			numCuesLabel.setText(((Integer)number).toString() + " cue");
		else
			numCuesLabel.setText(((Integer)number).toString() + " cues");

	}
	
	public void delete()
	{
		if(currentlyHighlighted != null)
		{
			cueArea.remove(currentlyHighlighted);
			this.invalidate();
			this.validate();
			this.repaint();
		}
	}
}
